/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "OneToOne.h"

@implementation OneToOne
- (id) init
{
	self = [super init];
	send = [[NSMutableDictionary alloc] init];
	recv = [[NSMutableDictionary alloc] init];
	novo = [[NSMutableDictionary alloc] init];
	return self;
}

- (void) dealloc
{
	[send release];
	[recv release];
	[super dealloc];
}

- (void) cleanForPos: (NSString *) pos
{
	int i;
	NSMutableArray *x = [novo objectForKey: pos];
	for (i = 0; i < [x count]; i++){
		NSMutableDictionary *y = [x objectAtIndex: i];
		NSString *sender, *sendertime, *receiver, *receivertime, *key;
		sender = [y objectForKey: @"sender"];
		sendertime = [y objectForKey: @"sendertime"];
		receiver = [y objectForKey: @"receiver"];
		receivertime = [y objectForKey: @"receivertime"];
		key = [y objectForKey: @"key"];
		if (sender != nil && sendertime != nil && receiver != nil &&
				receivertime != nil && key != nil){
			[x removeObjectAtIndex: i];
		}
	}
}

/**
 * Allocate an array for combination 'pos'
 */
- (void) allocateForPos: (NSString *) pos
{
	if ([novo objectForKey: pos] == nil){
		NSMutableArray *x = [[NSMutableArray alloc] init];
		[novo setObject: x forKey: pos];
		[x release];
	}
}

/**
 * if (mode = send) return the dictionary where send is nil
 * else if (mode = recv) return the dictionary where recv is nil
 */
- (NSMutableDictionary *) searchForPos: (NSString *) pos mode: (NSString *) mode
{
	NSMutableArray *x = [novo objectForKey: pos];
	int i, flag;

	if ([mode isEqual: @"send"]) flag = 1;
	else if ([mode isEqual: @"recv"]) flag = 2;
	else return nil;
	
	for (i = 0; i < [x count]; i++){
		NSMutableDictionary *p = [x objectAtIndex: i];
		NSString *isend = [p objectForKey: @"sender"];
		NSString *irecv = [p objectForKey: @"receiver"];
		if (flag == 1){
			if (isend == nil && irecv != nil){
				return p;
			}
		}else if (flag == 2){
			if (isend != nil && irecv == nil){
				return p;
			}	
		}
	}
	return nil;
}

- (NSMutableArray *) containerSend: (NSString *) container
	andSenderNode: (NSString *) senderNode
	andReceiverNode: (NSString *) receiverNode
	andTime: (NSString *) eventTime
	andOperation: (NSString *) operationName
	andProvider: (id<Integrator>) provider
{
//	int i;
	NSMutableArray *ret;

	ret = [[NSMutableArray alloc] init];

	NSString *pos = [NSString stringWithFormat: @"s%@-r%@",
		                         senderNode,receiverNode];
	[self allocateForPos: pos];
	NSMutableDictionary *kk = [self searchForPos: pos mode: @"send"];
	NSString *keytobeused = nil;
	if (kk == nil){
		static int key = 0;
		keytobeused = [NSString stringWithFormat: @"r%d", key];
		NSMutableDictionary *pp = [[NSMutableDictionary alloc] init];
		[pp setObject: container forKey: @"sender"];
		[pp setObject: eventTime forKey: @"sendertime"];
		[pp setObject: keytobeused forKey: @"key"];
		[[novo objectForKey: pos] addObject: pp];
		[pp release];
		key++;
	}else{
		[kk setObject: container forKey: @"sender"];
		[kk setObject: eventTime forKey: @"sendertime"];
		keytobeused = [kk objectForKey: @"key"];
	}
//	NSLog (@" SEND_IN - pos %@", pos);
//	NSLog (@"=> %@", [novo objectForKey: pos]);

	PajeStartLink *sl = [[PajeStartLink alloc]
		initWithTime: eventTime];
	[sl setContainer: [provider identifierForEntity:
		[NSArray arrayWithObjects: @"0", nil] ids:
		[NSArray arrayWithObjects: @"0", nil]]];
	[sl setSourceContainer: container];
	[sl setEntityType: [provider aliasToName:@"MPICommunication"]];
	[sl setValue: [provider aliasToName: @"send-recv"]];
	[sl setKey: keytobeused];
	[ret addObject: sl];
	[sl release];
		
	
/*	
	NSMutableArray *operations = [recv objectForKey: receiverNode];
	if (operations == nil){
		operations = [[NSMutableArray alloc] init];
		[recv setObject: operations forKey: receiverNode];
		[operations release];
		operations = [recv objectForKey: receiverNode];
	}

	if ([operations count] != 0){

		NSMutableDictionary *operation = [operations objectAtIndex: 0];
		[operation retain];
		[operations removeObjectAtIndex: 0];

		PajeStartLink *sl = [[PajeStartLink alloc]
			initWithTime: eventTime];
		[sl setContainer: [provider identifierForEntity:
			[NSArray arrayWithObjects: @"0", nil] ids:
			[NSArray arrayWithObjects: @"0", nil]]];
		[sl setSourceContainer: container];
		[sl setEntityType: [provider aliasToName:@"MPICommunication"]];
		[sl setValue: [provider aliasToName:
			[operation objectForKey: @"operation"]]];
		[sl setKey: [operation objectForKey: @"key"]];
		[ret addObject: sl];
		[sl release];
		
		[operation release];
	}else{ 
		static int skey = 0;
		NSString *key = [NSString stringWithFormat: @"%@%d",
			 operationName, skey];
		PajeStartLink *sl = [[PajeStartLink alloc]
			initWithTime: eventTime];
		[sl setContainer: [provider identifierForEntity:
			[NSArray arrayWithObjects: @"0", nil] ids:
			[NSArray arrayWithObjects: @"0", nil]]];
		[sl setSourceContainer: container];
		[sl setEntityType: [provider aliasToName:@"MPICommunication"]];
		[sl setValue: [provider aliasToName: operationName]];
		[sl setKey: key];
		[ret addObject: sl];
		[sl release];

		NSMutableDictionary *x = [[NSMutableDictionary alloc] init];
		[x setObject: key forKey: @"key"];
		[x setObject: operationName forKey: @"operation"];

		[[send objectForKey: receiverNode] addObject: x];
		skey++;
	}
	*/
	[ret autorelease];
	return ret;

}

- (NSMutableArray *) containerReceive: (NSString *) container
	andReceiverNode: (NSString *) receiverNode
	andSenderNode: (NSString *) senderNode
	andTime: (NSString *) eventTime
	andOperation: (NSString *) operationName
	andProvider: (id<Integrator>) provider
{
	NSMutableArray *ret = nil;
	
	ret = [[NSMutableArray alloc] init];

	NSString *pos = [NSString stringWithFormat: @"s%@-r%@",
			senderNode,receiverNode];
	[self allocateForPos: pos];
	NSMutableDictionary *kk = [self searchForPos: pos mode: @"recv"];
	NSString *keytobeused = nil;
	if (kk == nil){
		static int key = 0;
		keytobeused = [NSString stringWithFormat: @"r%d", key];
		NSMutableDictionary *pp = [[NSMutableDictionary alloc] init];
		[pp setObject: container forKey: @"receiver"];
		[pp setObject: eventTime forKey: @"receivertime"];
		[pp setObject: keytobeused forKey: @"key"];
		[[novo objectForKey: pos] addObject: pp];
		[pp release];
		key++;
	}else{
		[kk setObject: container forKey: @"receiver"];
		[kk setObject: eventTime forKey: @"receivertime"];
		keytobeused = [kk objectForKey: @"key"];
//		NSLog (@"%@", kk);
	}
//	NSLog (@"RECV_OUT - pos %@", pos);
//	NSLog (@"=> %@", [novo objectForKey: pos]);

//	[novo writeToFile: @"lucas" atomically: NO];
	
	PajeEndLink *el;
	el = [[PajeEndLink alloc] init];
	[el setTime: eventTime];
	[el setContainer: [provider identifierForEntity:
		[NSArray arrayWithObjects: @"0", nil] ids:
		[NSArray arrayWithObjects: @"0", nil]]];
	[el setDestContainer: container];
	[el setEntityType: [provider aliasToName:@"MPICommunication"]];
	[el setValue: [provider aliasToName: @"send-recv"]];
	[el setKey: keytobeused];
	[ret addObject: el];
	[el release];

	[self cleanForPos: pos];

	/*
	NSMutableArray *operations = [send objectForKey: senderNode];
	if (operations == nil){
		operations = [[NSMutableArray alloc] init];
		[send setObject: operations forKey: senderNode];
		[operations release];
		operations = [send objectForKey: senderNode];
	}

	if ([operations count] != 0){
		NSMutableDictionary *operation = [operations objectAtIndex: 0];
		[operation retain];
		[operations removeObjectAtIndex: 0];

		PajeEndLink *el;
		el = [[PajeEndLink alloc] init];
		[el setTime: eventTime];
		[el setContainer: [provider identifierForEntity:
			[NSArray arrayWithObjects: @"0", nil] ids:
			[NSArray arrayWithObjects: @"0", nil]]];
		[el setDestContainer: container];
		[el setEntityType: [provider aliasToName:@"MPICommunication"]];
		[el setValue: [provider aliasToName:
			[operation objectForKey: @"operation"]]];
		[el setKey: [operation objectForKey: @"key"]];
		[ret addObject: el];
		[el release];

		[operation release];
	}else{
		static int rkey = 0;

		NSString *key = [NSString stringWithFormat: @"%@%d",
			 operationName, rkey];
		PajeEndLink *el;
		el = [[PajeEndLink alloc] init];
		[el setTime: eventTime];
		[el setContainer: [provider identifierForEntity:
			[NSArray arrayWithObjects: @"0", nil] ids:
			[NSArray arrayWithObjects: @"0", nil]]];
		[el setDestContainer: container];
		[el setEntityType: [provider aliasToName:@"MPICommunication"]];
		[el setValue: [provider aliasToName: operationName]];
		[el setKey: key];
		[ret addObject: el];
		[el release];

		NSMutableDictionary *x = [[NSMutableDictionary alloc] init];
		[x setObject: key forKey: @"key"];
		[x setObject: operationName forKey: @"operation"];

		[[recv objectForKey: senderNode] addObject: x];
		rkey++;
	}
	*/

	[ret autorelease];
	return ret;
}

@end
